package com.hgyc.mom.eam.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hgyc.mom.common.enums.CommonOrderStatusEnum;
import com.hgyc.mom.common.enums.CommonStatus;
import com.hgyc.mom.common.exception.BizException;
import com.hgyc.mom.eam.entity.*;
import com.hgyc.mom.eam.enums.EquipmentCheckMaintainTypeEnum;
import com.hgyc.mom.eam.enums.EquipmentMaintainProgramTypeEnum;
import com.hgyc.mom.eam.job.QuartzPlanScheduler;
import com.hgyc.mom.eam.mapper.EamCheckMaintainPlanMapper;
import com.hgyc.mom.eam.service.*;
import com.hgyc.mom.eam.vo.EamCheckMaintainPlanVO;
import com.hgyc.mom.eam.vo.EamCheckReportVO;
import com.hgyc.mom.eam.vo.EamMaintainReportVO;
import com.hgyc.mom.tool.strategy.AutoCodeUtil;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.quartz.SchedulerException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 设备点检保养计划Service业务层实现
 *
 * @author fwj
 * @since 2025-08-13
 */
@Slf4j
@Service
public class EamCheckMaintainPlanServiceImpl extends ServiceImpl<EamCheckMaintainPlanMapper, EamCheckMaintainPlan> implements EamCheckMaintainPlanService {

    @Autowired
    private EamCheckMaintainPlanEquipmentService eamCheckMaintainPlanEquipmentService;
    @Autowired
    private EamCheckMaintainPlanProgramService eamCheckMaintainPlanProgramService;

    @Autowired
    private EamCheckReportService eamCheckReportService;

    @Autowired
    private EamMaintainReportService eamMaintainReportService;

    @Autowired
    private QuartzPlanScheduler scheduler;

    @Autowired
    private AutoCodeUtil autoCodeUtil;

    @PostConstruct
    public void initPlans() throws Exception {
        List<EamCheckMaintainPlan> plans = getActivePlans();
        scheduler.schedulePlans(plans);
    }

    private List<EamCheckMaintainPlan> getActivePlans() {
        LambdaQueryWrapper<EamCheckMaintainPlan> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EamCheckMaintainPlan::getStatus, CommonStatus.ENABLE.getValue());
        return list(queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void savePlan(EamCheckMaintainPlanVO eamCheckMaintainPlanVO) {
        eamCheckMaintainPlanVO.setStatus(CommonStatus.DISABLE.getValue().toString());
        save(eamCheckMaintainPlanVO);

        //新增设备点检保养计划设备信息
        List<EamCheckMaintainPlanEquipment> equipments = eamCheckMaintainPlanVO.getAddEquipments();
        if (!CollectionUtils.isEmpty(equipments)) {
            equipments.forEach(item -> {
                item.setId(null);
                item.setPlanId(eamCheckMaintainPlanVO.getId());
            });
            eamCheckMaintainPlanEquipmentService.saveBatch(equipments);
        }
        //新增设备点检保养计划项目
        List<EamCheckMaintainPlanProgram> programs = eamCheckMaintainPlanVO.getAddPrograms();
        if (!CollectionUtils.isEmpty(programs)) {
            programs.forEach(item -> {
                item.setId(null);
                item.setPlanId(eamCheckMaintainPlanVO.getId());
            });
            eamCheckMaintainPlanProgramService.saveBatch(programs);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePlan(EamCheckMaintainPlanVO eamCheckMaintainPlanVO) {
        // TODO 其他逻辑
        updateById(eamCheckMaintainPlanVO);

        //删除设备点检保养计划设备信息
        if (!CollectionUtils.isEmpty(eamCheckMaintainPlanVO.getDeleteEquipmentIds())) {
            eamCheckMaintainPlanEquipmentService.removeBatchByIds(eamCheckMaintainPlanVO.getDeleteEquipmentIds());
        }

        //新增设备点检保养计划设备信息
        List<EamCheckMaintainPlanEquipment> equipments = eamCheckMaintainPlanVO.getAddEquipments();
        if (!CollectionUtils.isEmpty(equipments)) {
            equipments.forEach(item -> {
                item.setId(null);
                item.setPlanId(eamCheckMaintainPlanVO.getId());
            });
            eamCheckMaintainPlanEquipmentService.saveBatch(equipments);
        }

        //更新设备点检保养计划设备信息
        if (!CollectionUtils.isEmpty(eamCheckMaintainPlanVO.getUpdateEquipments())) {
            List<EamCheckMaintainPlanEquipment> updateEquipments = eamCheckMaintainPlanVO.getUpdateEquipments();
            eamCheckMaintainPlanEquipmentService.updateBatchById(updateEquipments);
        }
        //删除设备点检保养计划项目
        if (!CollectionUtils.isEmpty(eamCheckMaintainPlanVO.getDeleteProgramIds())) {
            eamCheckMaintainPlanProgramService.removeBatchByIds(eamCheckMaintainPlanVO.getDeleteProgramIds());
        }

        //新增设备点检保养计划项目
        List<EamCheckMaintainPlanProgram> programs = eamCheckMaintainPlanVO.getAddPrograms();
        if (!CollectionUtils.isEmpty(programs)) {
            programs.forEach(item -> {
                item.setId(null);
                item.setPlanId(eamCheckMaintainPlanVO.getId());
            });
            eamCheckMaintainPlanProgramService.saveBatch(programs);
        }

        //更新设备点检保养计划项目
        if (!CollectionUtils.isEmpty(eamCheckMaintainPlanVO.getUpdatePrograms())) {
            List<EamCheckMaintainPlanProgram> updatePrograms = eamCheckMaintainPlanVO.getUpdatePrograms();
            eamCheckMaintainPlanProgramService.updateBatchById(updatePrograms);
        }

        // 更新定时任务
        try {
            if (CommonStatus.ENABLE.getValue().equals(eamCheckMaintainPlanVO.getStatus())) {
                EamCheckMaintainPlan plan = new EamCheckMaintainPlan();
                BeanUtils.copyProperties(eamCheckMaintainPlanVO, plan);
                scheduler.updatePlan(plan);
            }
        } catch (SchedulerException e) {
            log.error("更新点检保养计划定时任务失败！", e);
            throw new RuntimeException(e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removePlan(List<Long> ids) {
        // TODO 其他逻辑
        removeByIds(ids);
        //删除设备点检保养计划设备信息
        eamCheckMaintainPlanEquipmentService.deleteBatchByParentIds(ids);
        //删除设备点检保养计划项目
        eamCheckMaintainPlanProgramService.deleteBatchByParentIds(ids);
    }

    @Override
    public void excuteCreatePlan(Long planId) {
        if (planId == null) {
            throw new BizException("计划ID不能为空");
        }
        EamCheckMaintainPlan plan = getById(planId);
        if (plan == null) {
            throw new BizException("计划不存在");
        }
        List<EamCheckMaintainPlanEquipment> planEquipmentList = eamCheckMaintainPlanEquipmentService.getByParentId(planId);
        List<EamCheckMaintainPlanProgram> planProgramList = eamCheckMaintainPlanProgramService.getByParentId(planId);
        if (!CollectionUtils.isEmpty(planEquipmentList)) {
            planEquipmentList.forEach(equipment -> {
                if(EquipmentCheckMaintainTypeEnum.CHECK.getValue().equals(plan.getPlanType())) {
                    // 获取点检项目
                    List<EamCheckMaintainPlanProgram> checkProgramList = Optional.ofNullable(planProgramList)
                            .orElseGet(Collections::emptyList)
                            .stream()
                            .filter(program ->
                                    EquipmentMaintainProgramTypeEnum.SPOT_CHECK.getValue().equals(program.getType())
                            )
                            .collect(Collectors.toList());

                    if (!CollectionUtils.isEmpty(checkProgramList)) {
                        createCheckReport(plan, equipment.getEquipmentId(), checkProgramList);
                    }
                } else if (EquipmentCheckMaintainTypeEnum.MAINTAIN.getValue().equals(plan.getPlanType())) {
                    // 获取保养项目
                    List<EamCheckMaintainPlanProgram> maintainProgramList = Optional.ofNullable(planProgramList)
                            .orElseGet(Collections::emptyList)
                            .stream()
                            .filter(program ->
                                    EquipmentMaintainProgramTypeEnum.MAINTAIN.getValue().equals(program.getType())
                            )
                            .collect(Collectors.toList());


                    // 创建保养任务
                    if (!CollectionUtils.isEmpty(maintainProgramList)) {
                        createMaintainReport(plan, equipment.getEquipmentId(), maintainProgramList);
                    }
                }
            });
        }
    }

    /**
     * 创建点检任务
     * @param plan 计划
     * @param equipmentId 设备ID
     * @param programList 检验项目
     */
    private void createCheckReport(EamCheckMaintainPlan plan, Long equipmentId, List<EamCheckMaintainPlanProgram> programList) {
        EamCheckReportVO reportVO = new EamCheckReportVO();

        EamCheckReport report = new EamCheckReport();
        String equipmentCheckCode = autoCodeUtil.genSerialCode("equipment_check_code", null);
        report.setCode(equipmentCheckCode);
        report.setEquipmentId(equipmentId);
        report.setPlanId(plan.getId());
        report.setStartDate(plan.getStartDate());
        report.setEndDate(plan.getEndDate());
        report.setStatus(CommonOrderStatusEnum.PREPARE.getValue());
        report.setCreateBy(plan.getCreateBy());
        BeanUtils.copyProperties(report, reportVO);

        List<EamCheckReportLine> reportLines = new ArrayList<>();
        programList.forEach(program -> {
            EamCheckReportLine line = new EamCheckReportLine();
            line.setName(program.getName());
            line.setType(program.getType());
            line.setStandard(program.getStandard());
            line.setMaxValue(program.getMaxValue());
            line.setMinValue(program.getMinValue());
            line.setUnit(program.getUnit());
            line.setMethod(program.getMethod());
            line.setConsumable(program.getConsumable());
            line.setTool(program.getTool());
            reportLines.add(line);
        });
        reportVO.setAddReportLines(reportLines);

        eamCheckReportService.saveCheckReport(reportVO);
    }

    /**
     * 创建保养任务
     * @param plan 计划
     * @param equipmentId 设备ID
     * @param programList 检验项目
     */
    private void createMaintainReport(EamCheckMaintainPlan plan, Long equipmentId, List<EamCheckMaintainPlanProgram> programList) {
        EamMaintainReportVO reportVO = new EamMaintainReportVO();

        EamMaintainReport report = new EamMaintainReport();
        String reportCode = autoCodeUtil.genSerialCode("equipment_maintain_code", null);
        report.setCode(reportCode);
        report.setEquipmentId(equipmentId);
        report.setPlanId(plan.getId());
        report.setStartDate(plan.getStartDate());
        report.setEndDate(plan.getEndDate());
        report.setStatus(CommonOrderStatusEnum.PREPARE.getValue());
        report.setCreateBy(plan.getCreateBy());
        BeanUtils.copyProperties(report, reportVO);

        List<EamMaintainReportLine> reportLines = new ArrayList<>();
        programList.forEach(program -> {
            EamMaintainReportLine line = new EamMaintainReportLine();
            line.setName(program.getName());
            line.setType(program.getType());
            line.setStandard(program.getStandard());
            line.setMaxValue(program.getMaxValue());
            line.setMinValue(program.getMinValue());
            line.setUnit(program.getUnit());
            line.setMethod(program.getMethod());
            line.setConsumable(program.getConsumable());
            line.setTool(program.getTool());
            reportLines.add(line);
        });
        reportVO.setAddLines(reportLines);

        eamMaintainReportService.saveReport(reportVO);
    }

    @Override
    public void changeStatus(EamCheckMaintainPlan plan) {
        Long planId = plan.getId();
        String status = plan.getStatus();
        EamCheckMaintainPlan checkMaintainPlan = getById(planId);
        checkMaintainPlan.setStatus(status);
        updateById(checkMaintainPlan);

        // 更新定时任务
        try {
            if (CommonStatus.DISABLE.getValue().equals(status)) {
                scheduler.cancelPlan(plan.getId());
            } else if (CommonStatus.ENABLE.getValue().equals(status)) {
                scheduler.schedulePlan(plan);
            }
        } catch (SchedulerException e) {
            log.error("更新点检保养计划定时任务失败！", e);
            throw new RuntimeException(e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String importData(List<EamCheckMaintainPlan> eamCheckMaintainPlanList, boolean updateSupport) {
        if (eamCheckMaintainPlanList == null || eamCheckMaintainPlanList.isEmpty()) {
            throw new IllegalArgumentException("导入数据不能为空");
        }

        try {
            if (updateSupport) {
                // TODO 实现更新已有数据的导入逻辑
                return "更新导入成功，共导入 " + eamCheckMaintainPlanList.size() + " 条数据";
            } else {
                // TODO 实现不更新已有数据的导入逻辑
                return "新增导入成功，共导入 " + eamCheckMaintainPlanList.size() + " 条数据";
            }
        } catch (Exception e) {
            log.error("设备点检保养计划导入失败", e);
            throw new BizException("设备点检保养计划导入失败：" + e.getMessage());
        }
    }
}
